﻿using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Security.Principal;
using System.Data.Odbc;

/**
 * @file Database.cs Содержит необходимые внутренние методы для работы программы.
 * @author Максим Терентьев
 */

namespace DtpAdmin
{
    /** @class Database
     * @brief Класс описывающий и реализующий необходимые внутренние методы.
     * 
     * @details Класс описывающий и реализующий необходимые внутренние методы для авторизации, 
     * хранения сервисных переменных, и набор методов получения данных из БД.
     */
    class Database
    {
        /** @var String globalDatabaseName
         * @brief Название базы данных
         */
        static public String globalDatabaseName;
        /** @var String globalConnectionString
         * @brief Строка подключения к серверу БД
         */
        static public String globalConnectionString;
        //static public String globalConnectionString = @"Server=10.10.210.31;User=sa;Password=Qwerty123$;Initial Catalog=" + globalDatabaseName;

        /** @fn void InitDBengine()
         * @brief Инициализирует класс
         * @details Считывает строку подключения к базе даннх, либо берет настройки по-умолчанию
         */
        static public void InitDBengine()
        {
            // устанавливаем значения по умолчанию
            globalDatabaseName = "DTP";
            globalConnectionString = "Integrated security=sspi;Server=(local);Initial Catalog=" + globalDatabaseName;

            // читаем настройки из файла
            string configFileName = Application.ExecutablePath + ".cfg";
            FileInfo fi = new FileInfo(configFileName);
            if (fi.Exists)
            {
                try
                {
                    string[] s = File.ReadAllLines(configFileName);
                    if (s[0].Trim().Length != 0) globalConnectionString = s[0];
                }
                catch
                {
                    MessageBox.Show("Неверный формат файла конфигурации. Используем настройки по умолчанию", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
            }

            if (!WindowsIdentity.GetCurrent().IsAuthenticated)
            {
                MessageBox.Show("You are not authenticated by Windows.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                Environment.Exit(0);
            }
        }

        /** @fn bool TestConnection()
         * @brief Проверяет наличие подключения к базе
         * 
         * Проверяет наличие подключения к базе путем получения имени сервера.
         * @return @b true - если подключение установлено \n
         *         @b false - в противном случае.
         */
        static public bool TestConnection()
        {
            bool rslt = true;
            SqlConnection sql_con = new SqlConnection(globalConnectionString + ";Connection Timeout=3");
            try
            {
                SqlCommand command = new SqlCommand("SELECT @@SERVERNAME", sql_con);
                sql_con.Open();
                String sServername = command.ExecuteScalar().ToString();
            }
            catch (SqlException sEx)
            {
                rslt = false;
            }
            catch (Exception ex)
            {
                rslt = false;
            }
            finally
            {
                sql_con.Close();
            }
            return rslt;
        }

        /** @fn bool TestDBAccess()
         * @brief Проверяет наличие доступа к БД на сервере
         * 
         * @return @b true - если у текущего пользователя есть доступ к базе данных \n
         *         @b false - в противном случае.
         */
        static public bool TestDBAccess()
        {
            bool rslt = true;
            using (SqlConnection sql_con = new SqlConnection(globalConnectionString))
                try
                {
                    SqlCommand cmd = new SqlCommand("SELECT HAS_DBACCESS('" + globalDatabaseName + "')", sql_con);
                    cmd.Connection.Open();
                    rslt = cmd.ExecuteScalar().ToString() == "1";
                }
                catch (SqlException sEx)
                {
                    rslt = false;
                }
                catch (Exception ex)
                {
                    rslt = false;
                }
                finally
                {
                    sql_con.Close();
                }

            return rslt;
        }

        /** @fn bool TestSrvRole(String roleName)
         * @brief Проверяет наличие серверной роли у текущего пользователя
         * 
         * @param[in] roleName - название роли
         * @return @b true - если текущему пользователю присвоена необходимая серверная роль \n 
         *         @b false - в противном случае.
         */
        static public bool TestSrvRole(String roleName)
        {
            bool rslt = true;
            using (SqlConnection sql_con = new SqlConnection(globalConnectionString))
                try
                {
                    SqlCommand cmd = new SqlCommand("SELECT IS_SRVROLEMEMBER('" + roleName + "')", sql_con);
                    cmd.Connection.Open();
                    rslt = cmd.ExecuteScalar().ToString() == "1";
                }
                catch (SqlException sEx)
                {
                    rslt = false;
                }
                catch (Exception ex)
                {
                    rslt = false;
                }
                finally
                {
                    sql_con.Close();
                }

            return rslt;
        }

        /** @fn DataTable GetAllAccidentMemberTypes()
         * @brief Возвращает список всех категорий участников ДТП
         * @return Возвращает таблицу со списком категорий участников ДТП отсортированную по названию
         */
        static public DataTable GetAllAccidentMemberTypes()
        {
            DataTable rslt = new DataTable();
            using (SqlConnection connection = new SqlConnection(Database.globalConnectionString))
                try
                {
                    SqlDataAdapter MyDataAdapter = new SqlDataAdapter("SELECT * FROM dbo.GetAllAccidentMemberTypes() ORDER BY Description ASC", connection);
                    MyDataAdapter.Fill(rslt);
                    MyDataAdapter.Dispose();
                }
                catch (SqlException ex)
                {
                    if (ex.Class == 20)
                    {
                        // Connection failed
                        MessageBox.Show("Ошибка подключения", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                }
            return rslt;
        }

        /** @fn void AddAccidentMemberType(String accidentMemberType)
         * @brief Добавляет новую категорию участника ДТП в список
         * @param[in] accidentMemberType - Название новой категории
         */
        static public void AddAccidentMemberType(String accidentMemberType)
        {
            using (SqlConnection connection = new SqlConnection(Database.globalConnectionString))
                try
                {
                    SqlCommand cmd = new SqlCommand("AddDicAccidentMemberType", connection);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.Add(new SqlParameter("@p_value", SqlDbType.NVarChar, 256));
                    cmd.Parameters["@p_value"].Value = accidentMemberType.Trim();
                    cmd.Connection.Open();
                    cmd.ExecuteNonQuery();
                }
                catch (SqlException ex)
                {
                    if (ex.Class == 14)
                    {
                        // UNIQUE CONSTRAINT failed
                        MessageBox.Show("Такая категория уже существует", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    if (ex.Class == 20)
                    {
                        // Connection failed
                        MessageBox.Show("Ошибка подключения", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                }
        }

    }
}
